package jp.co.systemi.asp.workflow.peer;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import jp.co.systemi.asp.workflow.data.Apply;
import jp.co.systemi.asp.workflow.data.ApplyMeta;
import jp.co.systemi.asp.workflow.data.Common;
import jp.co.systemi.asp.workflow.data.PaidHoliday;
import jp.co.systemi.asp.workflow.data.PaidHolidayMeta;
import jp.co.systemi.asp.workflow.data.User;
import jp.co.systemi.asp.workflow.data.UserMeta;

import org.slim3.datastore.Datastore;

public class PaidHolidayPeer {

    private static final Logger log = Logger.getLogger(PaidHolidayPeer.class
            .getName());

    static SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");

    /**
     * 指定した社員の申請中または休暇予定の一覧を取得する
     *
     * @param loginId
     * @return
     */
    public static List<PaidHoliday> getHolidays(String loginId) {
        List<PaidHoliday> holidays = new ArrayList<PaidHoliday>();
        Calendar sysdate = Calendar.getInstance();
        sysdate.set(Calendar.HOUR, 0);
        sysdate.set(Calendar.MINUTE, 0);
        sysdate.set(Calendar.SECOND, 0);
        PaidHolidayMeta phm = PaidHolidayMeta.get();
        List<PaidHoliday> holidaysData = Datastore.query(phm).filter(
                phm.loginId.equal(loginId)).sort(phm.startDate.asc).asList();

        int i = 0;
        ApplyMeta am = ApplyMeta.get();
        for (PaidHoliday holiday : holidaysData) {
            if (holiday.getStatus().equals(Common.APPLY_STATUS.APPLYING)
                    || holiday.getStatus().equals(Common.APPLY_STATUS.APPROVED)) {
                if (holiday.getStartDate().compareTo(sysdate.getTime()) > 0) {
                    holidays.add(holiday);
                    holiday.setSeq(++i);
                    Apply apply = Datastore.query(am).filter(
                            am.id.equal(holiday.getApplyId())).asSingle();
                    if (apply != null) {
                        holiday.setStatus(apply.getStatus());
                    } else {
                        // error(getString("data.error"));
                        log.info("データ不整合？");
                    }
                }
            }
        }
        return holidays;
    }

    /**
     * 指定月の有給休暇一覧を取得する
     *
     * @param month
     * @return
     */
    public static List<PaidHoliday> getPaidHolidayData(Date month) {
        // マスタデータ（有給休暇残日数を取得）
        PaidHolidayMeta phm = PaidHolidayMeta.get();
        List<PaidHoliday> holidayMasterData = Datastore.query(phm).filter(
                phm.status.equal(Common.APPLY_STATUS.MASTER)).asList();
        UserMeta um = UserMeta.get();
        for (Iterator<PaidHoliday> itr = holidayMasterData.iterator(); itr
                .hasNext();) {
            PaidHoliday holiday = itr.next();
            // 社員番号
            User user = Datastore.query(um).filter(
                    um.loginId.equal(holiday.getLoginId())).asSingle();
            if (user == null) {
                log.info("ユーザー" + holiday.getLoginId() + "も存在しません。");
                itr.remove();
                continue;
            }
            holiday.setSeq(user.getSeq());
            holiday.setUserName(UserPeer.getName(user));
            // 該当月の有給休暇を取得
            List<PaidHoliday> holidays = Datastore.query(phm).filter(
                    phm.loginId.equal(holiday.getLoginId()),
                    phm.status.equal(Common.APPLY_STATUS.APPROVED)).asList();
            double days = 0;
            for (PaidHoliday day : holidays) {
                // 月を跨るに申請を許さない
                if (sdf.format(day.getStartDate()).compareTo(sdf.format(month)) == 0
                        && sdf.format(month).compareTo(
                                sdf.format(day.getEndDate())) == 0) {
                    days += day.getDays();
                }
            }
            holiday.setDays(days);

            // 残日数には来月未消化分を含まない
            List<PaidHoliday> futureHolidays = Datastore.query(phm).filter(
                    phm.loginId.equal(holiday.getLoginId())).asList();
            for (PaidHoliday future : futureHolidays) {
                if (future.getStatus().equals(Common.APPLY_STATUS.APPLYING)
                        || future.getStatus().equals(
                                Common.APPLY_STATUS.APPROVED)) {
                    if (sdf.format(future.getStartDate()).compareTo(
                            sdf.format(month)) > 0) {
                        holiday.setRemainingDays(holiday.getRemainingDays()
                                + future.getDays());
                    }
                }
            }
        }
        // 社員番号でソート
        Collections.sort(holidayMasterData, new ComparatorBySeq());
        return holidayMasterData;
    }

    public static class ComparatorBySeq implements Comparator<PaidHoliday> {

        public int compare(PaidHoliday h0, PaidHoliday h1) {
            return h0.getSeq() - h1.getSeq();
        }

    }
}
